/*
 * @Author: Yuluo 568055454@qq.com
 * @Date: 2023年06月17日 00:32:05
 * @LastEditors: Yuluo 568055454@qq.com
 * @LastEditTime: 2023年07月16日 03:47:11
 * @FilePath: \Mood-Blog-System\back\util\core\index.js
 * @Description: 核心工具函数
 * Copyright (c) 2023 by Yuluo, All Rights Reserved. 
 */
const fs = require('fs');
const path = require('path');

/**
 * @description: 请求成功模板
 * @param {import('koa').Context} ctx  包含request和response等信息的对象
 * @param {*} data 返回的数据, 默认：null
 * @param {String} message 返回的消息, 默认：request is success
 * @param {Number} code 返回的状态码, 默认：1
 * @return {void} 函数无返回值
 */
function success(ctx, data = null, message = 'request is success', code = 1) {
    ctx.body = {
        code,
        message,
        data,
    }
    return ctx.body;
}

/**
 * @description: 请求失败模板
 * @param {import('koa').Context} ctx 包含request和response等信息的对象
 * @param {String} message 返回的消息, 默认：request is fail
 * @param {Number} code 返回的状态码, 默认：0
 * @param {*} data  返回的数据, 默认：null
 * @return {void} 函数无返回值
 */
function fail(ctx, message = 'request is fail', code = 0, data = null,) {
    ctx.body = {
        code,
        message,
        error: data,
    }
    return ctx.body;
}

/**
 * @description: 分页处理
 * @param {import('sequelize').Model[]} data 查询的数据, 默认：[]
 * @param {Number} currentPage 当前页码, 默认：1
 * @param {Number} total 总条数, 默认：0
 * @param {Number} limit 限制每页条数, 默认：15
 * @param {String} message 返回的消息, 默认：request is success
 * @param {Number} code 返回的状态码, 默认：1
 * @return {{
 *  code: Number,
 *  message: String,
 *  data: import('sequelize').Model[],
 *  currentPage: Number,
 *  total: Number,
 *  totalPage: Number
 *  limit: Number
 * }} 返回一个对象包含：data, currentPage, total, totalPage(全部页), limit
 */
function paginate(ctx, data = [], currentPage = 1, total = 0, limit = 15, message = 'request is success', code = 1) {
    ctx.body = {
        code,
        message,
        data,
        currentPage: currentPage * 1,
        total,
        totalPage: Math.ceil(total / limit),
        limit: limit * 1,
    }
}

/**
 * @description: 递归读取文件夹下的所有文件
 * @param {String} path 文件夹路径
 * @param {Array} blackList 黑名单
 * @return {Array<NodeModule>} 返回一个数组，数组中的每一项是一个模块
*/
function completeRequire(path, blackList = []) {
    if (!path) throw new Error('path is required');
    return new Promise(async (resolve, reject) => {
        try {
            const files = fs.readdirSync(path);
            const modules = {};
            for (let i = 0; i < files.length; i++) {
                const file = files[i];
                const module = await require(`${path}/${file}`);
                modules[file] = module;
            }
            resolve(modules);
        } catch (error) {
            reject(error);
        }
    })
}
/**
 * @description: 首字母小写
 * @param {String} str 需要转换的字符串
 * @return {String} 转换后的字符串
 */
function firstLetterToLowerCase(str) {
    if (!str || str.length === 0) {
        return str; // 空字符串，不进行转换
    }
    return str.charAt(0).toLowerCase() + str.slice(1);
}

/**
 * @description: 首字母大写
 * @param {String} str 需要转换的字符串
 * @return {String} 转换后的字符串
*/
function firstLetterToUpperCase(str) {
    if (!str || str.length === 0) {
        return str; // 空字符串，不进行转换
    }
    return str.charAt(0).toUpperCase() + str.slice(1);
}

function getCallerFilePath() {
    const originalPrepareStackTrace = Error.prepareStackTrace;
    let callerFilePath;
    try {
        const error = new Error();
        Error.prepareStackTrace = function (error, stackTraces) {
            return stackTraces;
        };
        const stackTraces = error.stack;
        const callerFrame = stackTraces[2]; // 0: Error.prepareStackTrace, 1: getCallerFilePath, 2: caller function
        callerFilePath = callerFrame.getFileName();
    } catch (error) {
        // Ignore error
    }
    Error.prepareStackTrace = originalPrepareStackTrace;
    return callerFilePath;
}

/**
 * @description: 合并数组中的对象
 * @param {object[]} arr 需要合并的数组
 * @return {object} 返回合并后的对象
 */
function mergeArrayObj(arr = []) {
    return arr.reduce((prev, cur) => {
        return Object.assign(prev, cur);
    }, {})
}


function convertToString(data) {
    if (typeof data === 'object') {
        if (Array.isArray(data)) {
            // 处理数组
            let arrStr = '[';
            for (let i = 0; i < data.length; i++) {
                arrStr += convertToString(data[i]) + ', ';
            }
            arrStr = arrStr.slice(0, -2); // 去掉最后的逗号和空格
            arrStr += ']';
            return arrStr;
        } else {
            // 处理对象
            let objStr = '{';
            for (let key in data) {
                if (data.hasOwnProperty(key)) {
                    objStr += key + ': ' + convertToString(data[key]) + ', ';
                }
            }
            objStr = objStr.slice(0, -2); // 去掉最后的逗号和空格
            objStr += '}';
            return objStr;
        }
    } else {
        // 处理其他基本类型
        return String(data);
    }
}

function toJSON(obj) {
    if (!obj) return obj;
    if (typeof obj === 'string') {
        return obj
    }
    return JSON.stringify(obj);
}
function froJSON(obj) {
    if (!obj) return obj;
    if (typeof obj === 'string') {
        return obj
    }
    return JSON.parse(obj);
}

function getPositionByIp(ip) {
    return new Promise((resolve, reject) => {
        try {
            const ipnet = require('xz-ipnet')();
            const posInfoArr = ipnet.find(ip);
            resolve({
                code: 1, message: '获取成功', data: {
                    country: posInfoArr[0],
                    province: posInfoArr[1],
                    city: posInfoArr[2],
                    other: posInfoArr[3],
                    position: posInfoArr
                }
            })
        } catch (e) {
            reject({ code: 0, message: '获取失败', data: null })
        }
    })
}

function generateRandomCode(len) {
    return new Promise((resolve, reject) => {
        try {
            if (len <= 0) reject("生成的随机码位数不得小于0");
            // 定义包含数字和字母的字符集
            const characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
            let randomCode = '';

            // 生成随机六位数验证码
            for (let i = 0; i < len; i++) {
                const randomIndex = Math.floor(Math.random() * characters.length);
                randomCode += characters.charAt(randomIndex);
            }

            resolve(randomCode);
        } catch (error) {
            reject(error)
        }
    })
}

module.exports = {
    generateRandomCode,
    getPositionByIp,
    toJSON,
    froJSON,
    completeRequire,
    firstLetterToLowerCase,
    firstLetterToUpperCase,
    getCallerFilePath,
    mergeArrayObj,
    convertToString,
    success,
    fail,
    paginate
}